Conversation
07.ls_object/file.rb
Outdated
| @@ -0,0 +1,61 @@ | |||
| # frozen_string_literal: true | |||
|
|
|||
| module My | |||
There was a problem hiding this comment.
あまり My という意味のないモジュール名は使わないほうがよいように思います。
たしかに、サンプルコードなどでは MyClass などの My という言葉がよく使われますが、これは「なんかなんでもいいので私がつくったクラス」くらいの意味で、サンプルコードとしての簡便さをとっただけであり、実務では使わないです。基本的に意味のある名前をつけましょう。
There was a problem hiding this comment.
安易な命名でした。
FileMetadataに修正しました。
07.ls_object/file.rb
Outdated
|
|
||
| attr_reader :name | ||
|
|
||
| private_constant :FILE_TYPES, :PERMISSIONS |
07.ls_object/ls.rb
Outdated
| opt.parse(ARGV) | ||
|
|
||
| files = get_files(all, reverse) | ||
| puts long_format ? LongFormatLs.generate(files) : MultiColumnLs.generate(files) |
There was a problem hiding this comment.
フォーマットというのは出力制御の一種であり、それを元にコマンドやアプリケーション全体が分岐している、というのはちょっと違和感がありますね。
一般的に、プログラムは 入力 -> 演算 -> 出力 の3の部分で説明されることが多いです。この出力のところだけが全体部分に染み出してきているように見えます。
出力パーツが変化しうるもの、というくらいで捉えてはどうでしょうか。
07.ls_object/get_files.rb
Outdated
|
|
||
| require_relative 'file' | ||
|
|
||
| def get_files(all, reverse) |
There was a problem hiding this comment.
これだけ浮いているのもちょっと気になりますね。クラス設計は再度見直す必要がありそうです。
オブジェクト指向の設計で大事になってくるのは、何がコアとなるオブジェクトか、というところです。lsコマンドで一番重要な概念は何でしょう?たとえば、ファイルのメタデータ(ファイル名や作成日時など)をあつめたクラスをコアとして設計できそうではないでしょうか。
現状の My::File をたとえば FileMetadata などとリネームして、それをコアに据え、入力や出力は場合によって変わる、周辺的なもの、と考えましょう。そうすると
lsコマンドクラス
-> 入力を扱うクラス(今回だとオプションなど) -> FileMetadata
-> 出力を扱うクラス(今回だと標準出力) -> FileMetadata
みたいな依存関係にしておくと、FileMetadataは何にも依存していないので、コアとしてメンテしやすいクラスになりますし、もし出力がJSON形式になったとしても出力を扱うクラスを変更すればよいです。
このように考えてみてはどうでしょうか。
07.ls_object/long_format_ls.rb
Outdated
| COLUMN_COUNT = 1 | ||
| def initialize(files) | ||
| content_widths = calc_widths(files) | ||
| super(files, COLUMN_COUNT, content_widths) |
There was a problem hiding this comment.
ここでわざわざCOLUMN_COUNT=1でmatrixを使うのはかなり意味がないように思いますね。これもたぶん出力によって最初からわけてしまった影響だと思います。
表形式にしないといけないのは今回だと -l がない場合だけですよね。これは出力方式の関心事なので、 initialize で考慮しないといけない、というのはおかしい気がしますね。
07.ls_object/input_builder.rb
Outdated
| require 'optparse' | ||
| require_relative 'file' | ||
|
|
||
| class InputBuilder |
There was a problem hiding this comment.
ちょっと名前が抽象的すぎるので、もう少し特定のものが想起されるようにしましょう。説明的ですがCommandLineArgumentsParserとかですかね。
There was a problem hiding this comment.
クラスの役割を見直しにて修正しました。
また、コマンドライン引数をパースした結果filesが返ってくるというのは不自然であったため、ファイル取得のメソッドをクラスから外しました。
07.ls_object/ls.rb
Outdated
|
|
||
| class Ls | ||
| def self.run | ||
| files_and_option = InputBuilder.build |
There was a problem hiding this comment.
files, show_in_long_format = ...
みたいに分割代入するとわかりやすいように思います
07.ls_object/input_builder.rb
Outdated
| def self.build | ||
| input_builder = new | ||
| all, reverse, long_format = input_builder.parse_options | ||
| files = FileMetadata.get_files(all, reverse) |
There was a problem hiding this comment.
オプションとファイル取得までまとめたクラスを作るのであればこのクラス内にget_filesがあるほうがよい気がします。
There was a problem hiding this comment.
#12 (comment)
こちらで命名を修正した際、そもそも命名が曖昧になったのも引数のパースとファイル取得という別の役割のものが一つのクラスにまとまっていることが原因であると考え、ファイル取得をクラスから外しました。
get_filesはFileMetadataに持たせたまま、呼び出しをlsクラス内で行うようにしました。
| @long_format ? LongFormat.generate(@files) : MultiColumnFormat.generate(@files) | ||
| end | ||
|
|
||
| class MultiColumnFormat |
07.ls_object/file.rb
Outdated
|
|
||
| def initialize(name) | ||
| @name = name | ||
| @state = ::File.stat(name) |
There was a problem hiding this comment.
state ではなく stat ですね statistics の略だと思われます。
07.ls_object/input_builder.rb
Outdated
| opt.parse(ARGV) | ||
| [all, reverse, long_format] | ||
| end | ||
| end |
There was a problem hiding this comment.
結局オプションしか扱わない設計になったので、 CommandLineOptions くらいにしてもいいかなと思いました。
booleanの3つの値をそのまま返すと、自明でない順番に対する依存が発生します。最初がallというのはこのコードをちゃんと把握していないとわからないですよね。名前をつけたほうがよいです。
インスタンス変数で各オプションを持つようにして
def show_all?
@all
endなどとすると
options = CommandLineOptions.new
options.show_all?みたいにアクセスでき、よりわかりやすくなるかなと思います。
| require_relative 'multi_column_format' | ||
| require_relative 'long_format' | ||
|
|
||
| class DirectoryContentOutput |
There was a problem hiding this comment.
lsコマンドの実際の組み込み版を考えると、 ls hoge.rb みたいにファイル指定しての表示もできるので、必ずしもDirectoryが対象であるとは限りません。
FileListPrinter とかになるかなと思います。
There was a problem hiding this comment.
@yoshitsugu
フィヨルドの通知が死んでいるのでこちらでもメンションさせていただきます。
お時間あるときに確認お願いします。
File、Ls、MultiColumnLs、LongFormatLsという4つのクラスを定義して作成しました。testディレクトリ以下にはテストを記述したファイルとテスト用のファイルがあります。レビューお願いいたします。